package market

import (
	"context"
	"fmt"
	"math"
	"sync"
	"time"

	"monitor.ilin.cc/config"
	"monitor.ilin.cc/internal/services/alert"
)

type Monitor interface {
	OnTick(price float64, timestamp time.Time) error
}

type PriceChangeMonitor struct {
	alertService  alert.Service
	config        *config.RuntimePriceChangeAlert
	instID        string
	lastPrice     float64
	lastTime      time.Time
	alertBuffer   []*alert.Alert
	lastAlertTime time.Time
	bufferMu      sync.Mutex
}

func NewPriceChangeMonitor(instID string, cfg *config.PriceChangeAlert, alertService alert.Service) (*PriceChangeMonitor, error) {
	runtimeCfg, err := cfg.ToRuntime()
	if err != nil {
		return nil, fmt.Errorf("invalid config: %v", err)
	}

	return &PriceChangeMonitor{
		alertService: alertService,
		config:       runtimeCfg,
		instID:       instID,
	}, nil
}

func (m *PriceChangeMonitor) OnTick(price float64, timestamp time.Time) error {
	if m.lastPrice == 0 {
		m.lastPrice = price
		m.lastTime = timestamp
		return nil
	}

	// 计算价格变化
	change := (price - m.lastPrice) / m.lastPrice
	if math.Abs(change) >= m.config.Threshold {
		// 构建告警信息
		newAlert := &alert.Alert{
			Level: "warning",
			Title: fmt.Sprintf("%s 价格异常波动", m.instID),
			Content: fmt.Sprintf("产品: %s\n价格从 %.2f 变化到 %.2f，变化率 %.2f%%",
				m.instID, m.lastPrice, price, change*100),
			Timestamp: timestamp,
			Source:    "price_monitor",
			Tags: map[string]string{
				"inst_id": m.instID,
			},
		}

		// 尝试合并告警
		if err := m.bufferAlert(newAlert); err != nil {
			return fmt.Errorf("buffer alert failed: %v", err)
		}
	} else if timestamp.Sub(m.lastTime) >= m.config.Interval {
		// 更新基准价格
		m.lastPrice = price
		m.lastTime = timestamp
	}

	return nil
}

func (m *PriceChangeMonitor) bufferAlert(newAlert *alert.Alert) error {
	m.bufferMu.Lock()
	defer m.bufferMu.Unlock()

	now := time.Now()

	// 如果距离上次发送告警超过1分钟，或者缓冲区已满，则发送告警
	if now.Sub(m.lastAlertTime) >= time.Minute || len(m.alertBuffer) >= 5 {
		if len(m.alertBuffer) > 0 {
			// 合并消息
			content := fmt.Sprintf("%s 价格持续波动:\n", m.instID)
			for _, a := range m.alertBuffer {
				content += a.Content + "\n"
			}

			mergedAlert := &alert.Alert{
				Level:     "warning",
				Title:     fmt.Sprintf("%s 价格波动汇总", m.instID),
				Content:   content,
				Timestamp: now,
				Source:    "price_monitor",
				Tags: map[string]string{
					"inst_id": m.instID,
				},
			}

			// 发送合并后的告警
			if err := m.alertService.HandleAlert(context.Background(), mergedAlert); err != nil {
				return err
			}

			// 清空缓冲区
			m.alertBuffer = m.alertBuffer[:0]
			m.lastAlertTime = now
		}
	} else {
		// 添加到缓冲区
		m.alertBuffer = append(m.alertBuffer, newAlert)
	}

	return nil
}
